package sjtu.ist.warehouse4ws.action.file;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.struts2.json.annotations.JSON;
import org.xml.sax.SAXException;

import sjtu.ist.warehouse4ws.epc2bpmn.ParserEpc;
import sjtu.ist.warehouse4ws.model.DomainEpc;
import sjtu.ist.warehouse4ws.model.Domainmodel;
import sjtu.ist.warehouse4ws.model.Domainmodelattr;
import sjtu.ist.warehouse4ws.model.Domainmodelstate;
import sjtu.ist.warehouse4ws.model.Epcunit;
import sjtu.ist.warehouse4ws.model.Epcunits;
import sjtu.ist.warehouse4ws.model.Fileinfo;
import sjtu.ist.warehouse4ws.model.Functionpoint;
import sjtu.ist.warehouse4ws.model.FunctionpointEpc;
import sjtu.ist.warehouse4ws.model.Functions;
import sjtu.ist.warehouse4ws.model.Parameter;
import sjtu.ist.warehouse4ws.model.Process;
import sjtu.ist.warehouse4ws.model.Role;
import sjtu.ist.warehouse4ws.model.RoleEpc;
import sjtu.ist.warehouse4ws.service.DomainEpcService;
import sjtu.ist.warehouse4ws.service.DomainModelAttributeService;
import sjtu.ist.warehouse4ws.service.DomainModelService;
import sjtu.ist.warehouse4ws.service.DomainModelStateService;
import sjtu.ist.warehouse4ws.service.EpcUnitService;
import sjtu.ist.warehouse4ws.service.EpcunitsService;
import sjtu.ist.warehouse4ws.service.FileInfoService;
import sjtu.ist.warehouse4ws.service.FunctionpointEpcService;
import sjtu.ist.warehouse4ws.service.FunctionpointService;
import sjtu.ist.warehouse4ws.service.FunctionsService;
import sjtu.ist.warehouse4ws.service.ParameterService;
import sjtu.ist.warehouse4ws.service.ProcessService;
import sjtu.ist.warehouse4ws.service.RoleEpcService;
import sjtu.ist.warehouse4ws.service.RoleService;
import sjtu.ist.warehouse4ws.tool.Constants;
import sjtu.ist.warehouse4ws.tool.parser.DomainModelParser;
import sjtu.ist.warehouse4ws.tool.parser.EpcParser;
import sjtu.ist.warehouse4ws.tool.parser.FunctionPointParser;
import sjtu.ist.warehouse4ws.tool.parser.ProcessParser;

import com.opensymphony.xwork2.ActionSupport;

public class UpdateFileInfoAction extends ActionSupport {
	// input parameters
	// for updateFileInfo
	private String id;
	private String fileName;
	private String project;
	private String department;
	private String version;
	private int type;
	// for showEpcunits
	private Integer groupId;
	// for showOtherModels
	private String epcUnitType;
	private String epcUnitName;
	private String epcUnitId;
	private String epcUnitGroupId;
	private String epcUnitUid;

	// output parameters
	private boolean success = true;
	private List<Epcunits> eList = new ArrayList<Epcunits>();
	private String modelName;

	// base model service
	private FileInfoService fileInfoService;
	private EpcunitsService epcunitsService;
	private EpcUnitService epcUnitService;
	private ProcessService processService;
	private FunctionsService functionsService;
	private FunctionpointService functionpointService;
	private ParameterService parameterService;
	private DomainModelService domainModelService;
	private DomainModelAttributeService domainModelAttributeService;
	private DomainModelStateService domainModelStateService;
	private FunctionpointEpcService functionpointEpcService;
	private DomainEpcService domainEpcService;
	private RoleService roleService;
	private RoleEpcService roleEpcService;

	// model file type
	public static final int TYPE_PROCESS = 1;
	public static final int TYPE_FUNCTION = 2;
	public static final int TYPE_DEPARTMENT = 3;
	public static final int TYPE_DOMAIN = 4;
	public static final int TYPE_EPC = 5;
	public static final int TYPE_PERMISSION = 6;
	public static final int TYPE_ROLE = 7;

	/**
	 * 更新fileinfo 解析并存储其他模型
	 * 
	 * @return
	 */
	public String updateFileInfo() {
		Subject currentUser = SecurityUtils.getSubject();
		boolean admin = currentUser.hasRole("superadmin");
		int companyId = admin ? Constants.ADMIN_COMPANY_ID : 1;

		Fileinfo fileInfo = fileInfoService.getFileInfo(id, companyId);

		fileInfo.setProject(project);
		int groupInt;
		String groupId;
		String versionId;

		groupId = fileInfo.getGroupId();
		versionId = fileInfo.getVersionId();

		fileInfo.setDepartment(department);
		fileInfo.setType(type);
		fileInfo.setVersionId(versionId);

		String path = fileInfo.getXmlpath();
		int in = path.lastIndexOf("\\");
		String temp = path.substring(0, in + 1);
		String newDir = temp.concat(fileInfoService.getTypeById(type));
		String newPath = newDir + path.substring(in, path.length());

		// MyUtils.mkDirectory(newDir);
		// MyUtils.moveFile(path, newPath);
		fileInfo.setXmlpath(path);
		fileInfoService.updateFileInfo(fileInfo, companyId);

		parseById(type, path, id, groupId, versionId, companyId);

		success = true;
		return SUCCESS;
	}

	/**
	 * 解析模型文件
	 * 
	 * @param type
	 * @param path
	 * @param fileId
	 * @param groupId
	 * @param versionId
	 */
	private void parseById(int type, String path, String fileId,
			String groupId, String versionId, int companyId) {
		File file = new File(path);

		switch (type) {
		case TYPE_PROCESS: {
			ProcessParser pp = new ProcessParser(file);
			pp.parse();
			Process process = pp.getProcess();
			process.setFileId(fileId);
			process.setUid(java.util.UUID.randomUUID().toString());
			process.setGroupId(groupId);
			process.setVersionId(versionId);
			ArrayList<Functions> fs = pp.getFunList();

			processService.save(process);
			for (int i = 0; i < fs.size(); i++) {
				functionsService.save(fs.get(i), companyId);
			}

			break;
		}
		case TYPE_FUNCTION: {
			FunctionPointParser fpp = new FunctionPointParser(file);
			fpp.parse();
			Functionpoint fp = fpp.getFunctionPoint();
			fp.setFileId(fileId);
			fp.setUid(java.util.UUID.randomUUID().toString());
			fp.setGroupId(groupId);
			fp.setVersionId(versionId);
			// FileInfoAction.getFunctionList().add(fp);
			ArrayList<Parameter> param = fpp.getParamList();
			functionpointService.saveFunctionpoint(fp, companyId);
			for (int i = 0; i < param.size(); i++) {
				param.get(i).setFileId(fileId);
				param.get(i).setGroupId(groupId);
				param.get(i).setUid(java.util.UUID.randomUUID().toString());
				param.get(i).setVersionId(versionId);
				parameterService.save(param.get(i));
			}

			break;
		}
		case TYPE_DEPARTMENT:
			break;
		case TYPE_DOMAIN: {
			DomainModelParser dmp = new DomainModelParser(file);
			dmp.parse();
			Domainmodel dmodel = dmp.getDomainModel();
			dmodel.setFileId(fileId);
			dmodel.setUid(java.util.UUID.randomUUID().toString());
			dmodel.setGroupId(groupId);
			dmodel.setVersionId(versionId);
			ArrayList<Domainmodelattr> dmodelattr = dmp.getAttrList();
			ArrayList<Domainmodelstate> dmodelstate = dmp.getStateList();

			domainModelService.saveDomainModel(dmodel, companyId);
			for (int i = 0; i < dmodelattr.size(); i++) {
				dmodelattr.get(i)
						.setUid(java.util.UUID.randomUUID().toString());
				dmodelattr.get(i).setGroupId(groupId);
				dmodelattr.get(i).setVersionId(versionId);

				domainModelAttributeService.saveDomainModelAttribute(
						dmodelattr.get(i), companyId);
			}
			for (int i = 0; i < dmodelstate.size(); i++) {
				dmodelstate.get(i).setUid(
						java.util.UUID.randomUUID().toString());
				dmodelstate.get(i).setGroupId(groupId);
				dmodelstate.get(i).setVersionId(versionId);
				// FileInfoAction.getDomainList().add(dmodelstate.get(i));
				domainModelStateService.saveDomainmodelstate(
						dmodelstate.get(i), companyId);
			}
			break;
		}
		case TYPE_EPC: {
			// 解析后存入数据库
			List<Epcunits> epcunitsList = epcunitsService
					.getEpcunitsListById(fileId);
			if (epcunitsList.toString() == "[]") {
				EpcParser ep = new EpcParser(file);
				ep.parse();
				Epcunits epcunits = ep.getEpcUnits();

				epcunits.setFileId(fileId);
				epcunits.setUid(java.util.UUID.randomUUID().toString());
				epcunits.setGroupId(groupId);
				epcunits.setName(epcunits.getEpcUnits().get(0).getName());

				epcunits.setId(fileId);
				epcunits.setVersionId(versionId);
				epcunitsService.saveEpcUnits(epcunits, companyId);
				int in = path.lastIndexOf("\\");

				// FileInfoAction.getEpcunitList().add(epcunits);
				String epcId = fileId;
				List<Epcunit> list = epcunits.getEpcUnits();
				for (Epcunit epcunit : list) {
					epcunit.setEpcId(epcId);
					epcunit.setUid(java.util.UUID.randomUUID().toString());
					epcunit.setGroupId(groupId);
					epcunit.setVersionId(versionId);
					String eid = String.valueOf(epcunit.getId());
					String s = "";

					List<Integer> next = epcunit.getNext();

					for (int i : next) {
						s = s + i + ",";
					}
					epcunit.setNextstring(s);
					epcunit.setModelId(epcId + "_" + eid);
				}
				epcUnitService.addEpcUnit(list, companyId);
			}
			break;
		}

		}
	}

	/**
	 * 获得Epc列表
	 * 
	 * @return
	 */
	public String showEpcunit() {
		Subject currentUser = SecurityUtils.getSubject();
		boolean admin = currentUser.hasRole("superadmin");
		int companyId = admin ? Constants.ADMIN_COMPANY_ID : 1;

		eList = epcunitsService.getEpcunitsListByGroupAndVersion(
				String.valueOf(groupId), version, companyId);
		for (Epcunits e : eList) {
			List<Epcunit> euList = epcUnitService.getEpcunitListById(e.getId());
			e.setEpcUnits(euList);
			modelName = e.getName();
		}

		success = true;
		return SUCCESS;
	}

	public String showOtherModel() {
		Subject currentUser = SecurityUtils.getSubject();
		boolean admin = currentUser.hasRole("superadmin");
		int companyId = admin ? Constants.ADMIN_COMPANY_ID : 1;

		if (epcUnitType.equals("function")) {
			List<Functionpoint> funList = functionpointService
					.getFunctionpointListByGroupAndVersion(epcUnitGroupId,
							version, companyId);

			for (Functionpoint f : funList) {
				if (f.getEnName().equals(epcUnitName)) {
					FunctionpointEpc fpe = new FunctionpointEpc();
					fpe.setFunctionpoint(f.getId()); // 存储本来的Id
														// 依靠版本号来区分不同的模型版本
					fpe.setEpcUnit(epcUnitId);
					fpe.setEpcUid(epcUnitUid);
					fpe.setFunctionUid(f.getUid());
					fpe.setVersionId(version);
					fpe.setGroupId(epcUnitGroupId);
					functionpointEpcService.save(fpe, companyId);
					modelName = f.getCnName();
					break;
				}

			}
		} else if (epcUnitType.equals("event")) {
			List<Domainmodelstate> dmsList = domainModelStateService
					.getByGroupAndVersion(epcUnitGroupId, version, companyId);

			for (Domainmodelstate d : dmsList) {
				if (d.getEnName().equals(epcUnitName)) {
					DomainEpc de = new DomainEpc();
					de.setDomain(d.getDomainModelid()); // 存储本来的Id
														// 依靠版本号来区分不同的模型版本
					de.setEpcUnit(epcUnitId);
					de.setEpcUid(epcUnitUid);
					de.setDomainUid(d.getUid());
					de.setVersionId(version);
					domainEpcService.save(de, companyId);
					modelName = d.getCnName();
					break;
				}

			}
		} else {

			List<Role> roleList = roleService.getRoleListbyGroupId(
					epcUnitGroupId, companyId);
			for (Role role : roleList) {
				if (role.getEnName().equals(epcUnitName)) {
					RoleEpc re = new RoleEpc();
					re.setEpcUnit(epcUnitId);
					re.setRole(role.getId());
					re.setRoleUid(role.getUid());
					re.setEpcUid(epcUnitUid);
					re.setGroupId(epcUnitGroupId);
					re.setVersionId(version);
					roleEpcService.save(re, companyId);
					modelName = role.getCnName();

					break;
				}
			}
		}

		success = true;
		return SUCCESS;
	}

	// getters and setters
	public void setFileInfoService(FileInfoService fileInfoService) {
		this.fileInfoService = fileInfoService;
	}

	public void setEpcunitsService(EpcunitsService epcunitsService) {
		this.epcunitsService = epcunitsService;
	}

	public void setEpcUnitService(EpcUnitService epcUnitService) {
		this.epcUnitService = epcUnitService;
	}

	public void setProcessService(ProcessService processService) {
		this.processService = processService;
	}

	public void setFunctionsService(FunctionsService functionsService) {
		this.functionsService = functionsService;
	}

	public void setFunctionpointService(
			FunctionpointService functionpointService) {
		this.functionpointService = functionpointService;
	}

	public void setParameterService(ParameterService parameterService) {
		this.parameterService = parameterService;
	}

	public void setDomainModelService(DomainModelService domainModelService) {
		this.domainModelService = domainModelService;
	}

	public void setDomainModelAttributeService(
			DomainModelAttributeService domainModelAttributeService) {
		this.domainModelAttributeService = domainModelAttributeService;
	}

	public void setDomainModelStateService(
			DomainModelStateService domainModelStateService) {
		this.domainModelStateService = domainModelStateService;
	}

	public void setFunctionpointEpcService(
			FunctionpointEpcService functionpointEpcService) {
		this.functionpointEpcService = functionpointEpcService;
	}

	public void setDomainEpcService(DomainEpcService domainEpcService) {
		this.domainEpcService = domainEpcService;
	}

	public void setRoleService(RoleService roleService) {
		this.roleService = roleService;
	}

	public void setRoleEpcService(RoleEpcService roleEpcService) {
		this.roleEpcService = roleEpcService;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public void setProject(String project) {
		this.project = project;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	public void setGroupId(Integer groupId) {
		this.groupId = groupId;
	}

	public void setType(int type) {
		this.type = type;
	}

	public void setEpcUnitType(String epcUnitType) {
		this.epcUnitType = epcUnitType;
	}

	public void setEpcUnitName(String epcUnitName) {
		this.epcUnitName = epcUnitName;
	}

	public void setEpcUnitId(String epcUnitId) {
		this.epcUnitId = epcUnitId;
	}

	public void setEpcUnitGroupId(String epcUnitGroupId) {
		this.epcUnitGroupId = epcUnitGroupId;
	}

	public void setEpcUnitUid(String epcUnitUid) {
		this.epcUnitUid = epcUnitUid;
	}

	@JSON(name = "success")
	public boolean isSuccess() {
		return success;
	}

	@JSON(name = "epcUnit")
	public List<Epcunits> geteList() {
		return eList;
	}

	@JSON(name = "totalEpcUnit")
	public int getTotalEpcUnit() {
		return eList.size();
	}

	@JSON(name = "modelName")
	public String getModelName() {
		return modelName;
	}
}
